﻿
// MFCTest2View.cpp: CMFCTest2View 类的实现
//

#include "pch.h"
#include "framework.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义，并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "MFCTest2.h"
#endif

#include "MFCTest2Doc.h"
#include "MFCTest2View.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include "Option.h"


// CMFCTest2View

IMPLEMENT_DYNCREATE(CMFCTest2View, CView)

BEGIN_MESSAGE_MAP(CMFCTest2View, CView)
	ON_WM_CONTEXTMENU()
	ON_WM_RBUTTONUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_COMMAND(ID_DRAW_LINE, &CMFCTest2View::OnDrawLine)
	ON_COMMAND(ID_DRAW_ELLIPSE, &CMFCTest2View::OnDrawEllipse)
	ON_COMMAND(ID_DRAW_PEN, &CMFCTest2View::OnDrawPen)
	ON_COMMAND(ID_DRAW_RECT, &CMFCTest2View::OnDrawRect)
	ON_COMMAND(ID_DRAW_CIRCLE, &CMFCTest2View::OnDrawCircle)
	ON_WM_SIZE()
	ON_UPDATE_COMMAND_UI(ID_DRAW_CIRCLE, &CMFCTest2View::OnUpdateDrawCircle)
	ON_UPDATE_COMMAND_UI(ID_DRAW_ELLIPSE, &CMFCTest2View::OnUpdateDrawEllipse)
	ON_UPDATE_COMMAND_UI(ID_DRAW_LINE, &CMFCTest2View::OnUpdateDrawLine)
	ON_UPDATE_COMMAND_UI(ID_DRAW_PEN, &CMFCTest2View::OnUpdateDrawPen)
	ON_UPDATE_COMMAND_UI(ID_DRAW_RECT, &CMFCTest2View::OnUpdateDrawRect)
	ON_COMMAND(ID_FILE_OPTION, &CMFCTest2View::OnFileOption)
END_MESSAGE_MAP()

// CMFCTest2View 构造/析构

CMFCTest2View::CMFCTest2View() noexcept
{
	// TODO: 在此处添加构造代码
	m_bDraw = false;
	m_drawDt = DRAW_T::DT_LINE;
	m_rcLastLine = CPoint(-1, -1);
	m_pOrigin = CPoint(0, 0);
	m_nLineWidth = 1;
	m_nLineStyle = PS_SOLID;
	m_color = RGB(0, 0, 0);
	m_tempColor = RGB(255, 255, 255);
}

CMFCTest2View::~CMFCTest2View()
{
}

BOOL CMFCTest2View::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CView::PreCreateWindow(cs);
}

// 初始化内存DC和位图
void CMFCTest2View::InitMemDC(int width, int height)
{
	if (m_memDC.GetSafeHdc())
		m_memDC.DeleteDC();

	if (m_memBitmap.GetSafeHandle())
		m_memBitmap.DeleteObject();

	CClientDC dc(AfxGetMainWnd());

	m_memDC.CreateCompatibleDC(&dc);
	m_memBitmap.CreateCompatibleBitmap(&dc, width, height);
	m_memDC.SelectObject(&m_memBitmap);


	// 用白色填充
	m_memDC.FillSolidRect(0, 0, width, height, RGB(255, 255, 255));
}

// 初始化
void CMFCTest2View::OnInitialUpdate()
{
	CView::OnInitialUpdate();

	int screenWidth = GetSystemMetrics(SM_CXSCREEN);  // 获取主显示器宽度
	int screenHeight = GetSystemMetrics(SM_CYSCREEN); // 获取主显示器高度
	InitMemDC(screenWidth, screenHeight);

	CMFCTest2Doc* pDoc = GetDocument();

	if (pDoc->isOpenFile)
	{
		SetMemDC();
		pDoc->isOpenFile = false;
	}
	
	// TODO: 在此添加专用代码和/或调用基类
}

// CMFCTest2View 绘图

void CMFCTest2View::OnDraw(CDC* pDC)
{
	CMFCTest2Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CRect rect;
	GetClientRect(&rect);
	pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_memDC, 0, 0, SRCCOPY);
}

void CMFCTest2View::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
	ClientToScreen(&point);
	OnContextMenu(this, point);
}

void CMFCTest2View::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}


// CMFCTest2View 诊断

#ifdef _DEBUG
void CMFCTest2View::AssertValid() const
{
	CView::AssertValid();
}

void CMFCTest2View::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMFCTest2Doc* CMFCTest2View::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCTest2Doc)));
	return (CMFCTest2Doc*)m_pDocument;
}
#endif //_DEBUG

void CMFCTest2View::SetMemDC() {
	CMFCTest2Doc* pDoc = GetDocument();
	if (pDoc->m_tempImage.IsNull())
	{
		return;
	}
	
	int screenWidth = GetSystemMetrics(SM_CXSCREEN);  // 获取主显示器宽度
	int screenHeight = GetSystemMetrics(SM_CYSCREEN); // 获取主显示器高度
	m_memDC.BitBlt(0, 0, screenWidth, screenHeight,
		CDC::FromHandle(pDoc->m_tempImage.GetDC()), 0, 0, SRCCOPY);
	// 上面GetDC(),这里要Release
	pDoc->m_tempImage.ReleaseDC();
}

CDC* CMFCTest2View::GetMemDC()
{
	return &m_memDC;
}

CBitmap* CMFCTest2View::GetMemBitMap()
{
	return &m_memBitmap;
}

// CMFCTest2View 消息处理程序


void CMFCTest2View::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_pOrigin = point;
	m_bDraw = true;
	SetCapture();

	CView::OnLButtonDown(nFlags, point);
}


void CMFCTest2View::OnLButtonUp(UINT nFlags, CPoint point)
{
	
	if (m_bDraw) {
		m_bDraw = false;
		ReleaseCapture();

		CPen pen(m_nLineStyle, m_nLineWidth, m_color);
		CPen* pOldPen = m_memDC.SelectObject(&pen);
		// 用正常绘制模式画出线
		m_memDC.SelectStockObject(NULL_BRUSH);
		// 恢复默认绘图模式
		m_memDC.SetROP2(R2_COPYPEN);

		switch (m_drawDt)
		{
		case DRAW_T::DT_LINE:
			m_memDC.MoveTo(m_pOrigin);
			m_memDC.LineTo(point);
			m_rcLastLine = CPoint(-1, -1); // 初始化起点
			break;
		case DRAW_T::DT_RECT:
			m_memDC.Rectangle(m_rcLastEllipse);
			m_rcLastEllipse.SetRectEmpty();
			break;
		case DRAW_T::DT_ELLIPSE:
			m_memDC.Ellipse(m_rcLastEllipse);
			m_rcLastEllipse.SetRectEmpty();
			break;
		case DRAW_T::DT_PEN:
			m_memDC.MoveTo(m_pOrigin);
			m_memDC.LineTo(point);
			break;
		case DRAW_T::DT_CIRCLE:
			m_memDC.Ellipse(m_rcLastEllipse);
			m_rcLastEllipse.SetRectEmpty();
			break;
		default:
			break;
		}

		m_memDC.SelectObject(pOldPen);

		Invalidate(FALSE);
	}
	

	CView::OnLButtonUp(nFlags, point);
}

void CMFCTest2View::DrawLineRealTime(CPoint point) {
	CPen pen(m_nLineStyle, m_nLineWidth, m_tempColor);
	CPen* pOldPen = m_memDC.SelectObject(&pen);
	m_memDC.SelectStockObject(NULL_BRUSH);
	// 1. 擦除旧线（XOR 模式）
	m_memDC.SetROP2(R2_XORPEN);
	// 擦除旧线
	if (m_rcLastLine.x != -1 && m_rcLastLine.y != -1)
	{
		m_memDC.MoveTo(m_pOrigin);
		m_memDC.LineTo(m_rcLastLine);
	}
	m_rcLastLine = point;
	m_memDC.MoveTo(m_pOrigin);
	m_memDC.LineTo(m_rcLastLine);

	m_memDC.SelectObject(pOldPen);

	Invalidate(FALSE);
}

void CMFCTest2View::DrawPenRealTime(CPoint point) {
	CPen pen(m_nLineStyle, m_nLineWidth, m_color);
	CPen* pOldPen = m_memDC.SelectObject(&pen);

	m_memDC.MoveTo(m_pOrigin);
	m_memDC.LineTo(point);
	m_pOrigin = point;

	m_memDC.SelectObject(pOldPen);

	Invalidate(FALSE);
}

void CMFCTest2View::DrawRectRealTime(CPoint point) {
	CPen pen(m_nLineStyle, m_nLineWidth, m_tempColor);
	CPen* pOldPen = m_memDC.SelectObject(&pen);
	m_memDC.SelectStockObject(NULL_BRUSH);
	// 1. 擦除矩形（XOR 模式）
	m_memDC.SetROP2(R2_XORPEN);
	// 擦除矩形
	if (!m_rcLastEllipse.IsRectNull())
	{
		m_memDC.Rectangle(m_rcLastEllipse);
	}

	m_rcLastEllipse = CRect(m_pOrigin, point);
	m_memDC.Rectangle(m_rcLastEllipse);

	m_memDC.SelectObject(pOldPen);

	Invalidate(FALSE);
}

void CMFCTest2View::DrawCircleRealTime(CPoint point) {
	CPen pen(m_nLineStyle, m_nLineWidth, m_tempColor);
	CPen* pOldPen = m_memDC.SelectObject(&pen);
	m_memDC.SelectStockObject(NULL_BRUSH);
	// 1. 擦除圆（XOR 模式）
	m_memDC.SetROP2(R2_XORPEN);
	// 擦除圆
	if (!m_rcLastEllipse.IsRectNull())
	{
		m_memDC.Ellipse(m_rcLastEllipse);
	}

	int len = point.x - m_pOrigin.x;
	m_rcLastEllipse = CRect(m_pOrigin.x, m_pOrigin.y, m_pOrigin.x + len, m_pOrigin.y + len);
	m_memDC.Ellipse(m_rcLastEllipse);

	m_memDC.SelectObject(pOldPen);

	Invalidate(FALSE);
}

void CMFCTest2View::DrawEllipseRealTime(CPoint point) {
	CPen pen(m_nLineStyle, m_nLineWidth, m_tempColor);
	CPen* pOldPen = m_memDC.SelectObject(&pen);
	m_memDC.SelectStockObject(NULL_BRUSH);
	// 1. 擦除椭圆（XOR 模式）
	m_memDC.SetROP2(R2_XORPEN);
	// 擦除椭圆
	if (!m_rcLastEllipse.IsRectNull())
	{
		m_memDC.Ellipse(m_rcLastEllipse);
	}
	m_rcLastEllipse = CRect(m_pOrigin, point);
	m_memDC.Ellipse(m_rcLastEllipse);

	m_memDC.SelectObject(pOldPen);

	// 该方法会调用OnDraw()
	Invalidate(FALSE);
}

void CMFCTest2View::OnMouseMove(UINT nFlags, CPoint point)
{
	if (m_bDraw) {
		switch (m_drawDt)
		{
		case DRAW_T::DT_LINE:
			DrawLineRealTime(point);
			break;
		case DRAW_T::DT_RECT:
			DrawRectRealTime(point);
			break;
		case DRAW_T::DT_ELLIPSE:
			DrawEllipseRealTime(point);
			break;
		case DRAW_T::DT_PEN:
			DrawPenRealTime(point);
			break;
		case DRAW_T::DT_CIRCLE:
			DrawCircleRealTime(point);
			break;
		default:
			break;
		}
	}
	CView::OnMouseMove(nFlags, point);
}

void CMFCTest2View::SetDrawColor(COLORREF color) {
	m_color = color;
	// 自动计算一个高对比度的临时颜色
	m_tempColor = RGB(
		255 - GetRValue(m_color),
		255 - GetGValue(m_color),
		255 - GetBValue(m_color)
	);
}

void CMFCTest2View::OnDrawLine()
{
	// TODO: 在此添加命令处理程序代码
	m_drawDt = DRAW_T::DT_LINE;
}


void CMFCTest2View::OnDrawEllipse()
{
	// TODO: 在此添加命令处理程序代码
	m_drawDt = DRAW_T::DT_ELLIPSE;
}


void CMFCTest2View::OnDrawPen()
{
	// TODO: 在此添加命令处理程序代码
	m_drawDt = DRAW_T::DT_PEN;
}


void CMFCTest2View::OnDrawRect()
{
	// TODO: 在此添加命令处理程序代码
	m_drawDt = DRAW_T::DT_RECT;
}


void CMFCTest2View::OnDrawCircle()
{
	// TODO: 在此添加命令处理程序代码
	m_drawDt = DRAW_T::DT_CIRCLE;
}


void CMFCTest2View::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	// TODO: 在此处添加消息处理程序代码
}


void CMFCTest2View::OnUpdateDrawCircle(CCmdUI* pCmdUI)
{
	// TODO: 在此添加命令更新用户界面处理程序代码
	pCmdUI->SetCheck(m_drawDt == DRAW_T::DT_CIRCLE);
}


void CMFCTest2View::OnUpdateDrawEllipse(CCmdUI* pCmdUI)
{
	// TODO: 在此添加命令更新用户界面处理程序代码
	pCmdUI->SetCheck(m_drawDt == DRAW_T::DT_ELLIPSE);
}


void CMFCTest2View::OnUpdateDrawLine(CCmdUI* pCmdUI)
{
	// TODO: 在此添加命令更新用户界面处理程序代码
	pCmdUI->SetCheck(m_drawDt == DRAW_T::DT_LINE);
}


void CMFCTest2View::OnUpdateDrawPen(CCmdUI* pCmdUI)
{
	// TODO: 在此添加命令更新用户界面处理程序代码
	pCmdUI->SetCheck(m_drawDt == DRAW_T::DT_PEN);
}


void CMFCTest2View::OnUpdateDrawRect(CCmdUI* pCmdUI)
{
	// TODO: 在此添加命令更新用户界面处理程序代码
	pCmdUI->SetCheck(m_drawDt == DRAW_T::DT_RECT);
}


void CMFCTest2View::OnFileOption()
{
	// TODO: 在此添加命令处理程序代码
	Option option;
	option.m_nLineWidth = m_nLineWidth;
	option.m_nLineStyle = m_nLineStyle;
	option.m_color = m_color;
	if (IDOK == option.DoModal()) {
		m_nLineWidth = option.m_nLineWidth;
		switch (option.m_nLineStyle)
		{
		case 0:
			m_nLineStyle = PS_SOLID;
			break;
		case 1:
			m_nLineStyle = PS_DASH;
			break;
		case 2:
			m_nLineStyle = PS_DOT;
			break;
		default:
			break;
		}
		SetDrawColor(option.m_color);
	}
}
